
unit game;

{$mode objfpc}{$H+}{$J-}

interface

uses SysUtils, sdl2, sdl2_image, input_handler, texture_manager,
  game_object, fgl, cfg, glog, vector2,enemy,player,background,game_state,menu_state;

type
  TGameObjectList = specialize TFPGList<TGameObject>;

  TGame = class
  private
    pw: PSDL_Window;
    pr: PSDL_Renderer;
    constructor Create;
  public
    isRunning: boolean;
    class function Instance: TGame;
    procedure Init(title: string; x, y, h, w, flags: integer);
    procedure Render();
    procedure Update();
    procedure HandleEvents();
    procedure Clean();
    procedure Tick();
  end;

implementation

var
  g: TGame;

procedure TGame.Tick;

var
  s, e: int64;
begin
  if not isRunning then
    exit;
  s := SDL_GetTicks();
  HandleEvents;
  Update;
  Render;
  e := round(DELAY_TIME + s - SDL_GetTicks());

  if isRunning and (e > 0) then
  begin
    //WritelnLog('delay: %d', [e]);
    SDL_Delay(e);
  end;

end;

class function TGame.Instance(): TGame;
begin
  if g = nil then
    g := TGame.Create;

  Result := g;
end;

constructor TGame.Create;
begin
  inherited Create;
end;

procedure TGame.Update();

var
  i: integer;
begin
  if not isRunning then
    exit;  
  (TGameStateMachine.Instance()).Update;
end;

procedure TGame.HandleEvents();

begin
  if not isRunning then
    exit;
  TInputHandle.Instance().update();
  if TInputHandle.Instance().IsQuit then
    Clean;
end;

procedure TGame.Clean();

var
  i: integer;
begin
  isRunning := False;

  TInputHandle.Instance().Free;
  TTextureManager.Instance().Free;
  (TGameStateMachine.Instance()).Free;
  SDL_DestroyWindow(pw);
  SDL_DestroyRenderer(pr);
  //TTF_Quit();
  IMG_Quit();
  SDL_Quit();
end;

procedure TGame.Render();

var
  i: integer;
begin
  if not isRunning then
    exit;
  SDL_RenderClear(pr);
  (TGameStateMachine.Instance()).Render();
  SDL_RenderPresent(pr);
end;



procedure TGame.Init(title: string; x, y, h, w, flags: integer);
var state:TGameState;
begin
  SDL_Init(SDL_INIT_VIDEO);
  if SDL_WasInit(SDL_INIT_VIDEO) <> 0 then
    writelnlog('video init');

  pw := SDL_CreateWindow(PChar(title), x, y, h, w, flags);
  if pw <> nil then
    writelnlog('window init');

  pr := SDL_CreateRenderer(pw, -1, SDL_RENDERER_ACCELERATED or
    SDL_RENDERER_PRESENTVSYNC);
  if pr <> nil then
    writelnlog('renderer init');

  SDL_SetRenderDrawColor(pr, 238, 238, 238, 125);

  TInputHandle.Instance().InitJoysticks;

  state := TPlayState.Create(pr);

  (TGameStateMachine.Instance()).pushState(state);
  isRunning := True;
end;


end.
